package api

import (
	"moss/conf"
	"moss/fs"
	"moss/meta"
	"moss/status"
	"time"
)

func PutSymlink(requestId, accessKeyId, bucketName, objectName, targetObjectName, permission, userMeta string, contentLength int64) status.Status {
	if !validIdentifier(bucketName) {
		return status.InvalidBucketName
	}
	if !validIdentifier(objectName) || !validIdentifier(targetObjectName) {
		return status.InvalidObjectName
	}

	if getSizeOfUserMeta(userMeta) > conf.UserMetaMaxSize {
		return status.InternalError
	}

	objectInfo, ok := meta.GetObjectInfo(bucketName, objectName)
	if ok {
		if !checkObjectAclByBucketName(objectInfo.BucketName, objectInfo.Permission, objectInfo.OwnerAccessKeyId, accessKeyId, conf.AccessTypeWrite) {
			return status.AccessDenied
		}
		if objectInfo.Type != conf.ObjectTypeSymlink {
			return status.InvalidObjectName
		}
	} else {
		bucketMeta, ok := meta.GetBucketInfo(bucketName)
		if !ok {
			return status.NoSuchBucket
		}
		if !checkBucketACL(bucketMeta.Permission, bucketMeta.OwnerAccessKeyId, accessKeyId, conf.AccessTypeWrite) {
			return status.AccessDenied
		}
	}

	fileLocation := fs.GetObjectLocation(bucketName, objectName, 0)
	tag := fs.GenerateSymlinkUUID(bucketName, objectName, conf.Config.Security.AesPrivateKey)
	if len(tag) == 0 {
		return status.InternalError
	}

	meta.SetObjectInfo(bucketName, objectName, accessKeyId, tag, fileLocation, permission, "",
		conf.ObjectTypeSymlink, targetObjectName, userMeta, "", time.Now().Format(time.RFC3339), contentLength)

	return status.Success
}

func GetSymlink(requestId, accessKeyId, bucketName, objectName string) (map[string]string, status.Status) {
	if !validIdentifier(bucketName) {
		return nil, status.InvalidBucketName
	}
	if !validIdentifier(objectName) {
		return nil, status.InvalidObjectName
	}

	objectInfo, ok := meta.GetObjectInfo(bucketName, objectName)
	if !ok {
		return nil, status.NoSuchKey
	}
	if !checkObjectAclByBucketName(objectInfo.BucketName, objectInfo.Permission, objectInfo.OwnerAccessKeyId, accessKeyId, conf.AccessTypeRead) {
		return nil, status.AccessDenied
	}

	return map[string]string{conf.HTTPHeaderOssSymlinkTarget: objectInfo.SymlinkTarget, conf.HTTPHeaderEtag: objectInfo.ETag}, status.Success
}
